home *** CD-ROM | disk | FTP | other *** search
/ Clickx 115 / Clickx 115.iso / software / tools / windows / tails-i386-0.16.iso / live / filesystem.squashfs / etc / NetworkManager / dispatcher.d / 20-time.sh < prev    next >
Encoding:
Linux/UNIX/POSIX Shell Script  |  2013-01-06  |  7.4 KB  |  262 lines

  1. #!/bin/sh
  2.  
  3. # Rationale: Tor needs a somewhat accurate clock to work.
  4. # If the clock is wrong enough to prevent it from opening circuits,
  5. # we set the time to the middle of the valid time interval found
  6. # in the Tor consensus, and we restart it.
  7. # In any case, we use HTP to ask more accurate time information to
  8. # a few authenticated HTTPS servers.
  9.  
  10. # Get LIVE_USERNAME
  11. . /etc/live/config.d/username.conf
  12.  
  13. # Import tor_control_*(), tor_is_working(), TOR_LOG, TOR_DIR
  14. . /usr/local/lib/tails-shell-library/tor.sh
  15.  
  16. ### Init variables
  17.  
  18. TORDATE_DIR=/var/run/tordate
  19. TORDATE_DONE_FILE=${TORDATE_DIR}/done
  20. TOR_CONSENSUS=${TOR_DIR}/cached-microdesc-consensus
  21. TOR_UNVERIFIED_CONSENSUS=${TOR_DIR}/unverified-microdesc-consensus
  22. TOR_UNVERIFIED_CONSENSUS_HARDLINK=${TOR_UNVERIFIED_CONSENSUS}.bak
  23. INOTIFY_TIMEOUT=60
  24. DATE_RE='[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9]'
  25. VERSION_FILE=/etc/amnesia/version
  26.  
  27. ### Exit conditions
  28.  
  29. # Run only when the interface is not "lo":
  30. if [ "$1" = "lo" ]; then
  31.     exit 0
  32. fi
  33.  
  34. # Run whenever an interface gets "up", not otherwise:
  35. if [ "$2" != "up" ]; then
  36.     exit 0
  37. fi
  38.  
  39. # Do not run twice
  40. if [ -e "$TORDATE_DONE_FILE" ]; then
  41.     exit 0
  42. fi
  43.  
  44.  
  45. ### Create status directory
  46. install -o root -g root -m 0755 -d ${TORDATE_DIR}
  47.  
  48.  
  49. ### Functions
  50.  
  51. log() {
  52.     logger -t time "$@"
  53. }
  54.  
  55. notify_user() {
  56.     local summary="$1"
  57.     local body="$2"
  58.  
  59.     if [ -n "$3" ]; then
  60.         timeout_args='--expire-time=$3'
  61.     fi
  62.     export DISPLAY=':0.0'
  63.     export XAUTHORITY="`echo /var/run/gdm3/auth-for-${LIVE_USERNAME}-*/database`"
  64.     exec /bin/su -c "notify-send ${timeout_args} \"${summary}\" \"${body}\"" "${LIVE_USERNAME}" &
  65. }
  66.  
  67. has_consensus() {
  68.     local files="${TOR_CONSENSUS} ${TOR_UNVERIFIED_CONSENSUS}"
  69.  
  70.     if [ $# -ge 1 ]; then
  71.         files="$@"
  72.     fi
  73.     grep -qs "^valid-until ${DATE_RE}"'$' ${files}
  74. }
  75.  
  76. has_only_unverified_consensus() {
  77.     [ ! -e ${TOR_CONSENSUS} ] && has_consensus ${TOR_UNVERIFIED_CONSENSUS}
  78. }
  79.  
  80. wait_for_tor_consensus_helper() {
  81.     tries=0
  82.     while ! has_consensus && [ $tries -lt 5 ]; do
  83.         inotifywait -q -t 30 -e close_write -e moved_to ${TOR_DIR} || log "timeout"
  84.         tries=$(expr $tries + 1)
  85.     done
  86.  
  87.     # return some kind of success measurement
  88.     has_consensus
  89. }
  90.  
  91. wait_for_tor_consensus() {
  92.     log "Waiting for a Tor consensus file to contain a valid time interval"
  93.     if ! has_consensus && ! wait_for_tor_consensus_helper; then
  94.         log "Unsuccessfully waited for Tor consensus, restarting Tor and retrying."
  95.         restart-tor
  96.     fi
  97.     if ! has_consensus && ! wait_for_tor_consensus_helper; then
  98.         log "Unsuccessfully retried waiting for Tor consensus, aborting."
  99.     fi
  100.     if has_consensus; then
  101.         log "A Tor consensus file now contains a valid time interval."
  102.     else
  103.         log "Waited for too long, let's stop waiting for Tor consensus."
  104.         # FIXME: gettext-ize
  105.         notify_user "Synchronizing the system's clock" \
  106.             "Could not fetch Tor consensus."
  107.         exit 2
  108.     fi
  109. }
  110.  
  111. wait_for_working_tor() {
  112.     log "Waiting for Tor to be working (i.e. cached descriptors exist)..."
  113.     while ! tor_is_working; do
  114.         inotifywait -q -t ${INOTIFY_TIMEOUT} -e close_write -e moved_to ${TOR_DIR} || log "timeout"
  115.     done
  116.     log "Tor is now working."
  117. }
  118.  
  119. date_points_are_sane() {
  120.     local vstart="$1"
  121.     local vend="$2"
  122.  
  123.     vendchk=$(date -ud "${vstart} -0300" +'%F %T')
  124.     [ "${vend}" = "${vendchk}" ]
  125. }
  126.  
  127. time_is_in_valid_tor_range() {
  128.     local curdate="$1"
  129.     local vstart="$2"
  130.  
  131.     vendcons=$(date -ud "${vstart} -0230" +'%F %T')
  132.     order="${vstart}
  133. ${curdate}
  134. ${vendcons}"
  135.     ordersrt=$(echo "${order}" | sort)
  136.  
  137.     [ "${order}" = "${ordersrt}" ]
  138. }
  139.  
  140. maybe_set_time_from_tor_consensus() {
  141.     local consensus=${TOR_CONSENSUS}
  142.  
  143.     if has_only_unverified_consensus \
  144.        && ln -f ${TOR_UNVERIFIED_CONSENSUS} ${TOR_UNVERIFIED_CONSENSUS_HARDLINK}; then
  145.         consensus=${TOR_UNVERIFIED_CONSENSUS_HARDLINK}
  146.         log "We do not have a Tor verified consensus, let's use the unverified one."
  147.     fi
  148.  
  149.     log "Waiting for the chosen Tor consensus file to contain a valid time interval..."
  150.     while ! has_consensus ${consensus}; do
  151.         inotifywait -q -t ${INOTIFY_TIMEOUT} -e close_write -e moved_to ${TOR_DIR} || log "timeout"
  152.     done
  153.     log "The chosen Tor consensus now contains a valid time interval, let's use it."
  154.  
  155.  
  156.     # Get various date points in Tor's format, and do some sanity checks
  157.     vstart=$(sed -n "/^valid-after \(${DATE_RE}\)"'$/s//\1/p; t q; b; :q q' ${consensus})
  158.     vend=$(sed -n "/^valid-until \(${DATE_RE}\)"'$/s//\1/p; t q; b; :q q' ${consensus})
  159.     vmid=$(date -ud "${vstart} -0130" +'%F %T')
  160.     log "Tor: valid-after=${vstart} | valid-until=${vend}"
  161.  
  162.     if ! date_points_are_sane "${vstart}" "${vend}"; then
  163.         log "Unexpected valid-until: [${vend}] is not [${vstart} + 3h]"
  164.         return
  165.     fi
  166.  
  167.     curdate=$(date -u +'%F %T')
  168.     log "Current time is ${curdate}"
  169.  
  170.     if time_is_in_valid_tor_range "${curdate}" "${vstart}"; then
  171.         log "Current time is in valid Tor range"
  172.         return
  173.     fi
  174.  
  175.     log "Current time is not in valid Tor range, setting to middle of this range: [${vmid}]"
  176.     date -us "${vmid}" 1>/dev/null
  177.  
  178.     # Tor is unreliable with picking a circuit after time change
  179.     restart-tor
  180. }
  181.  
  182. tor_cert_valid_after() {
  183.     # Only print the last = freshest match
  184.     sed -n 's/^.*certificate lifetime runs from \(.*\) through.*$/\1/p' \
  185.         ${TOR_LOG} | tail -n 1
  186. }
  187.  
  188. tor_bootstrap_progress() {
  189.     grep -o "\[notice\] Bootstrapped [[:digit:]]\+%:" ${TOR_LOG} | \
  190.         tail -n1 | sed "s|\[notice\] Bootstrapped \([[:digit:]]\+\)%:|\1|"
  191. }
  192.  
  193. tor_cert_lifetime_invalid() {
  194.     # To be sure that we only grep relevant information, we
  195.     # should delete the log when Tor is started, which we do
  196.     # in 10-tor.sh.
  197.     # The log severity will be "warn" if bootstrapping with
  198.     # authorities and "info" with bridges.
  199.     grep -q "\[\(warn\|info\)\] Certificate \(not yet valid\|already expired\)\." \
  200.         ${TOR_LOG}
  201. }
  202.  
  203. # This check is blocking until Tor reaches either of two states:
  204. # 1. Tor completes a handshake with an authority (or bridge).
  205. # 2. Tor fails the handshake with all authorities (or bridges).
  206. # Since 2 essentially is the negation of 1, one of them will happen,
  207. # so it won't block forever. Hence we shouldn't need a timeout.
  208. # FIXME: An exception would be if Tor has DisableNetwork=1, which we
  209. # will use once we fully support bridge mode, so we will have to
  210. # revisit this then.
  211. is_clock_way_off() {
  212.     log "Checking if system clock is way off"
  213.     until [ "$(tor_bootstrap_progress)" -gt 10 ]; do
  214.         if tor_cert_lifetime_invalid; then
  215.             return 0
  216.         fi
  217.         sleep 1
  218.     done
  219.     return 1
  220. }
  221.  
  222. start_notification_helper() {
  223.     export DISPLAY=':0.0'
  224.     export XAUTHORITY="$(echo /var/run/gdm3/auth-for-$LIVE_USERNAME-*/database)"
  225.     exec /bin/su -c /usr/local/bin/tails-htp-notify-user "$LIVE_USERNAME" &
  226. }
  227.  
  228.  
  229. ### Main
  230.  
  231. start_notification_helper
  232.  
  233. # Delegate time setting to other daemons if Tor connections work
  234. if tor_is_working; then
  235.     log "Tor has already opened a circuit"
  236. else
  237.     # Since Tor 0.2.3.x Tor doesn't download a consensus for
  238.     # clocks that are more than 30 days in the past or 2 days in
  239.     # the future.  For such clock skews we set the time to the
  240.     # authority's cert's valid-after date.
  241.     if is_clock_way_off; then
  242.         log "The clock is so badly off that Tor cannot download a consensus. Setting system time to the authority's cert's valid-after date and trying to fetch a consensus again..."
  243.         date --set="$(tor_cert_valid_after)" > /dev/null
  244.         service tor reload
  245.     fi
  246.     wait_for_tor_consensus
  247.     maybe_set_time_from_tor_consensus
  248. fi
  249.  
  250. wait_for_working_tor
  251.  
  252. # Disable "info" logging workaround from 10-tor.sh
  253. if grep -qw bridge /proc/cmdline; then
  254.     tor_control_setconf "Log=\"notice file ${TOR_LOG}\""
  255. fi
  256.  
  257. touch $TORDATE_DONE_FILE
  258.  
  259. log "Restarting htpdate"
  260. service htpdate restart
  261. log "htpdate service restarted with return code $?"
  262.